package com.wbdca.crawler;


import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import com.wbdca.crawler.common.ConnectionPool;
import com.wbdca.crawler.common.FineGrainedTokens;
import com.wbdca.crawler.common.JsonStreamReader;
import com.wbdca.crawler.common.Message;
import com.wbdca.crawler.entity.Repository;
import com.wbdca.crawler.entity.User;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.net.URIBuilder;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;

public class Crawler {
    private static final String authorityURL = "https://api.github.com";

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
//        String login = "AlmasB";
//        User user = getUserByLogin(login);
//        JsonFileWriter.write(user);
//        System.out.println(ConnectionPool.limitRemain);
//        System.out.println(getRepositoryByUrl("https://github.com/AlmasB/FXGL"));

//        User user = new User("dependabot[bot]");
//        user.updateProfile();

//        Repository repository = getRepositoryByUrl("https://github.com/AlmasB/FXGL");
        Repository repository = getRepositoryByUrl("https://github.com/scrapy/scrapy");
        File DIR = new File("./Datas");
        if(!DIR.exists()){
            DIR.mkdir();
        }
        File dir = new File("./Datas/" + repository.getName());
        System.out.println("Making Directory " + dir.mkdir());
        repository.fetchContributors();
        repository.write();

//        System.out.println(getYearlyContributions("https://github.com/torvalds?tab=overview&from=2022-11-01&to=2022-11-28"));
        long endTime = System.currentTimeMillis();
        System.out.println((endTime - startTime) / 1000.0 + " secs.");
    }

    private static Repository getRepositoryByUrl(String url) {
        Repository repository;

        if(!url.startsWith("https://github.com/")) {
            Message.warn("Crawler.getRepositoryByURl", "Illegal url " + url);
            return null;
        }
        try {
            CloseableHttpClient client = ConnectionPool.getClient();
            HttpGet httpGet = new HttpGet(new URIBuilder(url
                    .replaceFirst("https://github.com", authorityURL + "/repos")).build());
            FineGrainedTokens.addAuthorization(httpGet);
            CloseableHttpResponse response = client.execute(httpGet);
            JsonReader reader = new JsonReader(new InputStreamReader(response.getEntity().getContent()));
//            CloseableHttpResponse response = ConnectionPool.getResponse(new URIBuilder(url.replaceFirst("https://github.com", authorityURL + "/repos")).build());
//            JsonReader reader = new JsonReader(new InputStreamReader(response.getEntity().getContent()));
            repository = JsonStreamReader.readRepositoryByReader(reader);
            httpGet.reset();
        } catch (URISyntaxException | IOException e) {
            throw new RuntimeException(e);
        }
        return repository;
    }

    private static Repository getRepositoryById(long id) {
        JsonReader reader;
        String name;
        CloseableHttpResponse response;
        Repository repo = new Repository(id);
        try {
            response = ConnectionPool.getResponse(new URIBuilder(authorityURL).appendPath("repositories").appendPath(String.valueOf(id)).build());
            if(response == null){
                Message.warn("Crawler.getRepositoryById", "Get repository " + id + " info unsuccessfully (No such repository).");
                return null;
            }
            reader = new JsonReader(new InputStreamReader(response.getEntity().getContent()));

            reader.beginObject();

            reader.endObject();
        } catch (URISyntaxException | IOException e) {
            throw new RuntimeException(e);
        }
        return repo;
    }

    /**
     * Not recommended.
     * @param url in format of https://github.com/{user}?tab=overview&from={yyyy-mm-dd}&to={yyyy-mm-dd}
     * @return yearly contribution in String format
     */
    private static String getYearlyContributions(String url) {
        String contribution = null;
        CloseableHttpResponse response = null;
        try {
            response = ConnectionPool.getResponse(new URI(url));
            Document document = Jsoup.parse(EntityUtils.toString(response.getEntity(), "UTF-8"));
            Elements yearlyContribution = document.getElementsByClass("f4 text-normal mb-2");
            contribution = yearlyContribution.text();
        } catch (URISyntaxException | ParseException | IOException e) {
            throw new RuntimeException(e);
        }
        return contribution;
    }
}
